package com.jsyso.jsyso.db.id;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;

/**
 * MySql序列生成器
 * @author janjan, xujian_jason@163.com
 *
 */
public class MySqlSequence implements Sequence {
	private static final Logger logger = LoggerFactory.getLogger(MySqlSequence.class);
	
	// 数据库操作对象集合
	private NamedParameterJdbcOperations[] jdbcs;
	// 记录当前索引
	private int index = -1;
	
	public void setJdbcs(NamedParameterJdbcOperations[] jdbcs) {
		this.jdbcs = jdbcs;
	}
	
	/**
	 * 从数据库中获取ID
	 * @return
	 */
	protected Long getId(int index, final String tableName) {
		return jdbcs[index].getJdbcOperations().execute(new ConnectionCallback<Long>() {
			public Long doInConnection(Connection con) throws SQLException, DataAccessException {
				String replaceSql = "REPLACE INTO " + tableName + "(stub) VALUES('a')";
				int update = con.prepareStatement(replaceSql).executeUpdate();
				if(update > 0) {
					ResultSet rs = con.prepareStatement("SELECT LAST_INSERT_ID()").executeQuery();
					rs.first();
					if(rs != null){
						return rs.getLong(1);
					}
				}
				return 0l;
			}
		});
	}
	
	@Override
	public Long nextVal(String seqName) {
		int i = this.index + 1, j = this.index;
		boolean clockWise = true;
		for(; i<jdbcs.length || j >= 0; 
				++i, clockWise = i<jdbcs.length) {
			try {
				Long id = this.getId(clockWise ? i : j--, seqName);
				if(id > 0) {
					return id;
				}
			} catch (Exception e) {
				logger.warn("[MySqlSequence nextVal error] count = " + this.index, e);
				continue;
			} finally {
				this.index = clockWise ? i : j + 1;
			}
		}
		return 0l;
	}
	
}
